#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.${artifactId}.web.filter;

import groovy.util.logging.Slf4j;
import groovyjarjarantlr4.v4.runtime.misc.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.${artifactId}.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.UUID;

/**
 * @Author: shenyang
 * @CreateTime: 2023-01-17  09:51
 * @Description: TODO
 * @Version: 1.0
 */
@Component
@WebFilter(filterName = "authenticationFilter", urlPatterns = "/*")
@Order(-9999)
@Slf4j
public class RestLogFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(RestLogFilter.class);

    private static final String TRACE_ID = "xRequestId";

    @Override
    public void doFilterInternal(@NotNull HttpServletRequest httpServletRequest, @NotNull HttpServletResponse httpServletResponse, FilterChain chain)
            throws IOException, ServletException {
        MDC.put(TRACE_ID, UUID.randomUUID().toString().replaceAll("-", ""));
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(httpServletRequest);
        ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(httpServletResponse);
        long start = (new Date()).getTime();

        chain.doFilter(wrappedRequest, wrappedResponse);

        long end = (new Date()).getTime();
        String requestUri = httpServletRequest.getRequestURI();        // 请求的
        String queryParam = httpServletRequest.getQueryString();        // 查询参数
        String method = httpServletRequest.getMethod();                // 请求方法
        // 请求体
        // 转换为字符串，在限制请求体大小的情况下，因为字节数据不完整，这里可能乱码，
        String requestBody = new String(wrappedRequest.getContentAsByteArray(), StandardCharsets.UTF_8);
        // 响应体
        String responseBody = new String(wrappedResponse.getContentAsByteArray(), StandardCharsets.UTF_8);

        // 记录请求信息
        logger.info("路径={},方法={}，请求参数={}", requestUri, method, requestBody);
        // 记录response信息
        logger.info("请求参数={}，返回={}，时间={}", requestBody, responseBody, end - start);
        // 这一步很重要，把缓存的响应内容，输出到客户端
        wrappedResponse.copyBodyToResponse();
    }
}
